////////////////////////////////////////////////////////////////////////////////
/*!	\file		c45.cpp
**	\brief		Defines all methods declared in c45.hpp
**	\author		Nate Cleveland
**	\date		11/18/2002 3:30:38 PM
**	\par		DESCRIPTION:
**				 See header for description.
**					
**	\par		REMARKS:
**					
*/
////////////////////////////////////////////////////////////////////////////////
#include "C45Generator.hpp"
#include "treeFileIO.hpp"
#include "C45.hpp"
#include <fstream>
#include <memory.h>
#include <stdio.h>
#include <map>
using namespace DTree;


const float DTree::C45_MIN_EXAMPLES = 0;

//See Header for documentation.
C45::C45()
:AI_System::AI_Unit(AI_System::TT_C45), m_root(NULL)
{
	
	
}

//See Header for documentation.
C45::~C45()
{
	if(m_root) 
		delete m_root;

	trainingExamples.clear();
}

//See Header for documentation.
C45::C45(const C45& toCopyFrom) throw()
:AI_System::AI_Unit(toCopyFrom), m_root(NULL)
{
	//don't bother copying if we don't have any data.
	if(toCopyFrom.m_root)
	{
		//allocate a new node for the tree.
		m_root = new C45Node;
		
		//Do a deep copy of our tree.
		C45Node::DeepCopy(*(toCopyFrom.m_root), *(this->m_root));
	}
}


//See Header for documentation.
void C45::train(void) throw()
{
	//we must set a minimum level of examples.
	if(trainingExamples.size() < C45_MIN_EXAMPLES)
		return;
	
	//create a vector and fill it with all the classes we use.
	std::vector<bool> classVec;
	classVec.push_back(false);
	classVec.push_back(true);

	try
	{
		//Create an object to build our new tree from all given examples.
		C45Generator<C45, AIUnitAdapter> c45Builder(*this, classVec);
		c45Builder();

		//Clear out all used examples.
		this->trainingExamples.clear();	


	}  catch(...)
	{
		//If the root isn't null after an error, make it so.
		if(m_root)
			delete m_root;
		
		
	}//end catch
}


//See Header for documentation.
bool C45::save(void) throw()
{
/*	char buffer[256] = {"dtree.acu"};
	printf("File to save to?");
	std::ofstream hFile(gets(buffer));


	//ignore for now
	//....
	TreeFileIO<C45::C45Node> treeIO(m_root, hFile);
*/
	return false;
}

//See Header for documentation.
bool C45::load() throw()
{
/*	char buffer[256] = {"dtree.acu"};
	printf("File to load from?");
	std::ifstream hFile(gets(buffer));
	//ignore for now
	//...

	TreeFileIO<C45::C45Node> treeIO(m_root, hFile);
*/
	return false;
}

//See Header for documentation.
bool C45::triggerAction() throw()
{
	//If we don't have any nodes yet just return true to all queryies.
	if(!m_root)
		return true;	

	//Recursively treverse the tree. See nodes.hpp for more details.
	return (*m_root)(attributes);
}


//See Header for documentation.
C45_ADN::C45_ADN()
:AI_System::AI_ADN(AI_System::TT_C45), m_root(NULL)
{
	//all done in init list.
	//...	
}

//See Header for documentation.
C45_ADN::~C45_ADN()
{
	//check for a non-null root and clear it .
	if(m_root) 
		delete m_root;

	//clean up all examples.
	trainingExamples.clear();
}

//See Header for documentation.
C45_ADN::C45_ADN(const C45_ADN& toCopyFrom) throw()
:AI_System::AI_ADN(toCopyFrom), m_root(NULL)
{
	//don't bother copying if we don't have any data.
	if(toCopyFrom.m_root)
	{
		//allocate a new node for the tree.
		m_root = new C45_ADN_Node;
		
		//Do a deep copy of our tree.
		C45_ADN_Node::DeepCopy(*(toCopyFrom.m_root), *(this->m_root));
	}
}


//See Header for documentation.
void C45_ADN::train(void) throw()
{
	//we must set a minimum level of examples.
	if(trainingExamples.size() < C45_MIN_EXAMPLES)
		return;

	//Create a vector of all classes used by this tree.
	std::vector<AI_System::AI_ID> classVec;
	std::map<AI_System::AI_ID, AI_System::AI_Unit*>::const_iterator aiUnitIT = AI_Units.begin();

	//fill the classVec with all aiUnits this ADN uses.
	for( ;aiUnitIT != AI_Units.end() ; aiUnitIT++)
		classVec.push_back((*aiUnitIT).second->getID());


	try
	{
		//create a c45Generator. This functor will build our new tree from
		// our given example set.
		C45Generator<C45_ADN, AIUnitAdapter> c45Builder(*this, classVec);
		c45Builder();

		//Clear out all used examples.
		trainingExamples.clear();	

	} catch(...)
	{
		//If the root isn't null after an error, make it so.
		if(m_root)
			delete m_root;
		
		
	}//end catch
}

//See Header for documentation.
bool C45_ADN::save(void) throw()
{
/*	char buffer[256] = {"dtree.acu"};
	printf("File to save to?");
	std::ofstream hFile(gets(buffer));


	//ignore for now
	//....
	TreeFileIO<C45_ADN_Node> treeIO(m_root, hFile);
*/
	return false;
}

//See Header for documentation.
bool C45_ADN::load() throw()
{
/*	char buffer[256] = {"dtree.acu"};
	printf("File to load from?");
	std::ifstream hFile(gets(buffer));
	//ignore for now
	//...

	TreeFileIO<C45_ADN_Node> treeIO(m_root, hFile);
*/	return false;
}

//See Header for documentation.
AI_System::AI_ID  C45_ADN::process()
{
	//If we don't have any nodes yet just pick a random one.
	if(!m_root)
	{
		//Create a vector of all classes used by this tree.
		std::vector<AI_System::AI_ID> classVec;
		std::map<AI_System::AI_ID, AI_System::AI_Unit*>::const_iterator aiUnitIT = AI_Units.begin();
		
		//fill the classVec with all aiUnits this ADN uses.
		for( ;aiUnitIT != AI_Units.end() ; aiUnitIT++)
			classVec.push_back((*aiUnitIT).second->getID());
		
		return classVec[rand() % classVec.size()];	
	}

	//Recursively treverse the tree. See nodes.hpp for more details.
	return (*m_root)(attributes);
}





